﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Campeonato.Model;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data.Common;
using System.Data;
using log4net;
using Campeonato.Common.Extensions;

namespace Campeonato.Common.DAL
{
    class JogadorDAL
    {
        private static ILog s_logger;
        private static ILog Logger
        {
            get
            {
                if (s_logger == null)
                {
                    s_logger = LogManager.GetLogger("JogadorDAL");
                }

                return s_logger;
            }
        }

        public void CadastrarJogador(int _campeonatoID, Jogador _jogador)
        {
            Database db = DatabaseFactory.CreateDatabase(DBHelper.PES_DATABASE);

            string sql = "INSERT INTO Pontuacao (pontos, num_vitorias, num_empates, num_derrotas, gols_pro, gols_contra) VALUES ({0}, {1}, {2}, {3}, {4}, {5})";

            string pontosParam = db.BuildParameterName("Pontos");
            string numVitParam = db.BuildParameterName("NumVit");
            string numEmpParam = db.BuildParameterName("NumEmp");
            string numDerParam = db.BuildParameterName("NumDer");
            string golsProParam = db.BuildParameterName("GolsPro");
            string golsContParam = db.BuildParameterName("GolsCont");

            sql = string.Format(sql, pontosParam, numVitParam, numEmpParam, numDerParam, golsProParam, golsContParam);

            DbCommand cmd = db.GetSqlStringCommand(sql);
            db.AddInParameter(cmd, pontosParam, DbType.Int32, 0);
            db.AddInParameter(cmd, numVitParam, DbType.Int32, 0);
            db.AddInParameter(cmd, numEmpParam, DbType.Int32, 0);
            db.AddInParameter(cmd, numDerParam, DbType.Int32, 0);
            db.AddInParameter(cmd, golsProParam, DbType.Int32, 0);
            db.AddInParameter(cmd, golsContParam, DbType.Int32, 0);

            using (DbConnection connection = db.CreateConnection())
            {
                connection.Open();
                DbTransaction transaction = connection.BeginTransaction();
                try
                {
                    db.ExecuteNonQuery(cmd, transaction);

                    sql = "SELECT @@IDENTITY Pontuacao";
                    cmd = db.GetSqlStringCommand(sql);
                    _jogador.Pontos = new Pontuacao();
                    _jogador.Pontos.ID = Convert.ToInt64(db.ExecuteScalar(cmd, transaction));

                    sql = "INSERT INTO Jogador (nome, time_escolhido, pontuacao_id) VALUES ({0}, {1}, {2})";

                    string nomeJogParam = db.BuildParameterName("NomeJog");
                    string timeParam = db.BuildParameterName("TimeJog");
                    string pontParam = db.BuildParameterName("PontID");

                    sql = string.Format(sql, nomeJogParam, timeParam, pontParam);

                    cmd = db.GetSqlStringCommand(sql);
                    db.AddInParameter(cmd, nomeJogParam, DbType.String, _jogador.Nome);
                    db.AddInParameter(cmd, timeParam, DbType.String, _jogador.TimeEscolhido);
                    db.AddInParameter(cmd, pontParam, DbType.Int64, _jogador.Pontos.ID);

                    db.ExecuteNonQuery(cmd, transaction);
                    sql = "SELECT @@IDENTITY Jogador";
                    cmd = db.GetSqlStringCommand(sql);
                    _jogador.ID = Convert.ToInt64(db.ExecuteScalar(cmd, transaction));

                    sql = "INSERT INTO Campeonato_Jogadores (campeonato_id, jogador_id) VALUES ({0}, {1})";
                    
                    string campIDParam = db.BuildParameterName("CampID");
                    string jogadorIDParam = db.BuildParameterName("JogID");

                    sql = string.Format(sql, campIDParam, _jogador.ID);
                    
                    cmd = db.GetSqlStringCommand(sql);
                    db.AddInParameter(cmd, campIDParam, DbType.Int32, _campeonatoID);
                    db.AddInParameter(cmd, jogadorIDParam, DbType.Int64, _jogador.ID);
                    
                    db.ExecuteNonQuery(cmd, transaction);

                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    Logger.Error("Ocorreu um erro ao salvar jogador.", ex);
                    transaction.Rollback();
                    throw;
                }
                finally
                {
                    connection.Close();
                }
            }

        }

        public IList<Jogador> BuscarJogadoresDisponiveisPorRodada(int _campeonatoID, int _rodada)
        {
            Database db = DatabaseFactory.CreateDatabase(DBHelper.PES_DATABASE);

            List<Jogador> lstJogadores = new List<Jogador>();

            string sql = @"SELECT
                                 J.jogador_id, 
                                 J.nome,
                                 J.time_escolhido,
                                 J.pontuacao_id
                            FROM 
                                 Jogador J,
                                 Campeonato_Jogadores CJ
                            WHERE 
                                 J.jogador_id = CJ.jogador_id AND
                                 CJ.campeonato_id = {0} AND
                                 J.jogador_id not in (
								 
								 SELECT jogador1_id 
								 FROM 
									Campeonato_Partidas CP, Partida P 
								 WHERE 
									P.partida_id = CP.partida_id AND 
									P.rodada = {1} AND
									CP.campeonato_id = {0} ) AND

								J.jogador_id not in (
								SELECT jogador2_id 
								 FROM 
									Campeonato_Partidas CP, Partida P 
								 WHERE 
									P.partida_id = CP.partida_id AND 
									P.rodada = {1} AND
									CP.campeonato_id = {0}
								)";

            string campIDParam = db.BuildParameterName("campID");
            string rodadaParam = db.BuildParameterName("rodadaID");
            sql = string.Format(sql, campIDParam, rodadaParam);

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, campIDParam, DbType.Int32, _campeonatoID);
            db.AddInParameter(cmd, rodadaParam, DbType.Int32, _rodada);

            using (IDataReader dbReader = db.ExecuteReader(cmd))
            {
                while (dbReader.Read())
                {
                    Jogador j = new Jogador();
                    j.ID = dbReader.GetInt64(0);
                    j.Nome = dbReader.GetString(1);
                    j.TimeEscolhido = dbReader.GetString(2);
                    if (!dbReader.IsDBNull(3))
                    {
                        j.Pontos = new Pontuacao();
                        j.Pontos.ID = dbReader.GetInt64(3);
                    }

                    lstJogadores.Add(j);
                }
            }

            return lstJogadores;
        }

        internal bool ExisteJogador(int _campeonatoID, string _nomeJogador)
        {
            Database db = DatabaseFactory.CreateDatabase(DBHelper.PES_DATABASE);

            string sql = @"SELECT COUNT(*) FROM 
                            Campeonato_Jogadores CJ, Jogador J 
                          WHERE 
                                J.nome = {0} AND 
                                J.jogador_id = CJ.jogador_id AND
                                CJ.campeonato_id = {1}";

            string nomeJogParam = db.BuildParameterName("NomeJog");
            string campIDParam = db.BuildParameterName("CampID");
            sql = string.Format(sql, nomeJogParam, campIDParam);
            DbCommand cmd = db.GetSqlStringCommand(sql);
            db.AddInParameter(cmd, nomeJogParam, DbType.String, _nomeJogador);
            db.AddInParameter(cmd, campIDParam, DbType.Int32, _campeonatoID);
            int count = Convert.ToInt32(db.ExecuteScalar(cmd));
            return count > 0;
        }

        internal IList<Jogador> BuscarJogadores(int _campeonatoID)
        {
            Database db = DatabaseFactory.CreateDatabase(DBHelper.PES_DATABASE);

            List<Jogador> lstJogadores = new List<Jogador>();

            string sql = @"SELECT
                                 J.jogador_id, 
                                 J.nome,
                                 J.time_escolhido,
                                 J.pontuacao_id
                            FROM 
                                 Jogador J,
                                 Campeonato_Jogadores CJ
                            WHERE 
                                 J.jogador_id = CJ.jogador_id AND
                                 CJ.campeonato_id = {0}
                            ORDER BY
                                 J.nome ASC";

            string campIDParam = db.BuildParameterName("campID");
            sql = string.Format(sql, campIDParam);

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, campIDParam, DbType.Int32, _campeonatoID);

            using (IDataReader dbReader = db.ExecuteReader(cmd))
            {
                while (dbReader.Read())
                {
                    Jogador j = new Jogador();
                    j.ID = dbReader.GetInt64(0);
                    j.Nome = dbReader.GetString(1);
                    j.TimeEscolhido = dbReader.GetString(2);
                    if (!dbReader.IsDBNull(3))
                    {
                        j.Pontos = new Pontuacao();
                        j.Pontos.ID = dbReader.GetInt64(3);
                    }

                    lstJogadores.Add(j);
                }
            }

            return lstJogadores;
        }

        internal Jogador BuscarJogador(long _jogadorID)
        {
            Database db = DatabaseFactory.CreateDatabase(DBHelper.PES_DATABASE);

            Jogador jogador = null;

            string sql = @"SELECT
                                 J.jogador_id, 
                                 J.nome,
                                 J.time_escolhido,
                                 J.pontuacao_id
                            FROM 
                                 Jogador J
                            WHERE 
                                 J.jogador_id = {0}
                            ORDER BY
                                 J.nome ASC";

            DbCommand cmd = db.CreateCommand(sql, DbParam.Create(_jogadorID));

            using (IDataReader dbReader = db.ExecuteReader(cmd))
            {
                if (dbReader.Read())
                {
                    jogador = new Jogador()
                    {
                        ID = dbReader.GetValue<long>(0),
                        Nome = dbReader.GetValue<string>(1),
                        TimeEscolhido = dbReader.GetValue<string>(2)
                    };

                    if (!dbReader.IsDBNull(3))
                    {
                        jogador.Pontos = new Pontuacao();
                        jogador.Pontos.ID = dbReader.GetValue<long>(3);
                    }
                }
            }

            return jogador;
        }
    }
}
